home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PAS_0793 / CDROM.PAS < prev    next >
Pascal/Delphi Source File  |  1993-08-01  |  16KB  |  521 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 317 of 373
  3. From : Marc Van Leeuwen                    2:285/228.0          25 Jun 93  12:09
  4. To   : Glen Washburn                       3:640/305.0
  5. Subj : Using CD-ROM Audio
  6. ────────────────────────────────────────────────────────────────────────────────
  7.  > I have an NEC CD-ROM and SB Pro package. It came with
  8.  > a program called CDPLYR that allows the user to play
  9.  > Audio CDs however it is very gludgy only plays the CDs
  10.  > in sequential order. Can I control this in PASCAL .
  11.  > I want to be able to play different tracks in any
  12.  > order. If I hade the interupts or what ever maybe I
  13.  > could figure it out for myself
  14.  
  15. I read this msg here a couple of months ago.
  16.  
  17. ===========================================================}
  18.  
  19. {(4319)  Fri 12 Feb 93 20:25
  20. By: Norbert Igl
  21. To: Pieter Lambrecht
  22. Re: (1) CD-Audio with TP
  23. St:
  24. ------------------------------------------------------------
  25.   hmmm, Sorry for the german remarks....(:-)
  26.  
  27. Part - 1 -
  28. }
  29. {$IFDEF DoNotCompileThis}
  30. Unit CDROM;
  31.  
  32. {  Unit talking to a CD-Rom-Drive
  33.    Low-level CD access,
  34.    only the first drive is supported...!
  35.    Copyright 1992  Norbert Igl  }
  36.  
  37. INTERFACE
  38.  
  39. TYPE
  40.    CD_RECORD = Record
  41.                     Status : Word;    { Status des Drives/letzte Funktion }
  42.                     DrvChar: Char;    { LW-Buchstabe }
  43.                     DrvNo  : Byte;    { als Byte ablegegt (0...) }
  44.                     HSG_RB : byte;    { Adressierungs-Modus }
  45.  
  46.                     Sector : LongInt; { Adresse des Lesekopfes }
  47.                     VolInfo: Array[1..8] of Byte; { Lautst.-Einstellungen }
  48.                     DevPar : LongInt; { Device-parameter, BIT-Feld! }
  49.                     RawMode: Boolean; { Raw/Cooked-Mode ? }
  50.                     SecSize: Word;    { bytes/Sector }
  51.                     VolSize: LongInt; { sek/Volume => Groesse der CD}
  52.  
  53.                     MedChg : Byte;    { Disk gewechselt? }
  54.  
  55.                     LoAuTr : Byte;    { kleinste Audio-Track # }
  56.                     HiAuTr : byte;    { groesste Audio-Track # }
  57.                     EndAdr : LongInt; { Adresse der Auslaufrille (8-) }
  58.  
  59.                     TrkNo  : Byte;    { Track #. Eingabe-Wert ! }
  60.                     TrkAdr : LongInt; { Adresse dieses Tracks }
  61.                     TrkInf : byte;    { Info dazu: BIT-Feld! }
  62.  
  63.                     CntAdr : byte;   { CONTROL und ADR, von LW }
  64.                     CTrk   : byte;   { track # }
  65.                     Cindx  : byte;   { point/index }
  66.                     CMin   : byte;   { minute\  }
  67.                     CSek   : byte;   { second > Laufzeit im Track }
  68.                     CFrm   : byte;   { frame /  }
  69.                     Czero  : byte;   { immer =0 }
  70.                     CAmin  : byte;   { minute \ }
  71.                     CAsec  : byte;   { sekunde > Laufzeit auf Disk }
  72.                     CAFrm  : byte;   { frame  / }
  73.  
  74.                     Qfrm   : LongInt;{ start-frame address }
  75.                     Qtrfs  : LongInt;{ Bufferaddresse }
  76.                     Qcnt   : LongInt;{ Anzahl der Sectoren }
  77.                       { pro Sector werden 96 byte nach buffer kopiert }
  78.  
  79.                     Uctrl  : byte;  { CONTROL und ADR byte }
  80.                     Upn    : Array[1..7] of Byte; { EAN-CODE }
  81.                     Uzero  : byte;  { immer = 0 }
  82.                     Ufrm   : byte;  { Frame-# }
  83.                   End;
  84.       OneTrack             = Record
  85.                                Title   : String[20];
  86.                                Runmin,
  87.                                RunSec :  Byte;
  88.                                Start  :  LongInt;  { HSG Format ! }
  89.                              end;
  90.       VolumeTableOfContens = Record
  91.                                Diskname: String[20];
  92.                                UAN_Code: String[13];
  93.                                TrackCnt: Byte;
  94.                                Titles  : Array[1..99] of OneTrack;
  95.                              end;
  96.        TrkInfo  = Record
  97.                      Nummer  : Byte;
  98.                      Start   : LongInt;
  99.                      Cntrl2  : Byte;
  100.                   end;
  101. {===== global verfuegbare Variablen =============}
  102.  
  103. VAR    CD           : CD_RECORD;
  104.        CD_AVAIL     : Boolean;
  105.        VTOC         : VolumeTableOfContens;
  106.        CD_REDPos    : String;
  107.        CD_HSGPos    : String;
  108.  
  109. {===== allgemeine Funktionen ===================}
  110.  
  111. Function CD_Reset   : Boolean;
  112. Function CD_HeadAdr : Boolean;
  113. Function CD_Position: Boolean;
  114. Function CD_MediaChanged: Boolean;
  115.  
  116.  
  117. {===== Tray/Caddy-Funktionen ===================}
  118.  
  119. Function CD_Open:  Boolean;
  120. Function CD_Close: Boolean;
  121. Function CD_Eject: Boolean;
  122.  
  123. {==== Audio-Funktionen =========================}
  124.  
  125. Function CD_Play(no:byte; len:integer):  Boolean;
  126. Function CD_Stop:  Boolean;
  127. Function CD_Resume:Boolean;
  128. Function CD_SetVol:Boolean;
  129. Function CD_GetVol:Boolean;
  130.  
  131. Procedure CD_Info;
  132. Procedure CD_TrackInfo( Nr:byte; VAR T:TrkInfo );
  133.  
  134. {==== Umwandlungen =============================}
  135.  
  136. function Red2Time( Var Inf:TrkInfo ):Word;
  137.  
  138. IMPLEMENTATION uses Dos;
  139. Type   IOCtlBlk = Array[0..200] of Byte;
  140.  
  141. Const  IOCtlRead  = $4402;
  142.        IOCtlWrite = $4403;
  143.        DevDrvReq  = $1510;
  144.        All:LongInt= $0f00;
  145.  
  146. Var  R        : Registers;
  147.      H        : Text;
  148.      Handle   : Word;
  149.      Old_Exit : Pointer;
  150.      CtlBlk   : IOCtlBlk;
  151.  
  152.      Tracks   : Array[1..100] of TrkInfo;
  153.  
  154. Procedure CD_Exit;               { wird bei Programmende ausgefuehrt }
  155. begin
  156.   if Old_Exit <> NIL
  157.     then ExitProc := Old_Exit;      { Umleitung wieder zuruecknehmen }
  158. {$I-}
  159.   Close(H);
  160.   If IoResult = 0 then;              { 'H' schliessen, falls offen, }
  161. {$I+}                                      { evtl. Fehler verwerfen }
  162. end;
  163.  
  164.  
  165. Function CD_Init:  Boolean;    { Initialisierung beim Programmstart }
  166. begin
  167.  FillChar( CD, Sizeof( CD ), 0);
  168.  with R do
  169.  begin
  170.    AX := $1500;
  171.    BX := $0000;
  172.    CX := $0000;
  173.    Intr( $2F, R );
  174.    CD_Init := (BX > 0);                  { Anzahl der CD-Laufwerke }
  175.    If BX > 0
  176.     then begin
  177.       CD.DrvChar                           { CD-Laufwerksbuchstabe }
  178.          := CHAR( CL + Byte('A') );
  179.       CD.DrvNo := CL;
  180.       If CD_HeadAdr then
  181.         If CD_GetVol then;
  182.     end
  183.     else CD.DrvChar := '?';                      { im Fehlerfall...}
  184.  end
  185. end;
  186.  
  187. Procedure CD_TrackInfo( Nr:byte; VAR T:TrkInfo );
  188. begin
  189.   T := Tracks[nr]
  190. end;
  191.  
  192. Function OpenCDHandle:Word;
  193. Const Name : String[8] = 'MSCD001';        { evt. anpassen!!! ? }
  194. begin
  195.   Assign(H, Name);                         { Filehandle holen }
  196. (*$I-*)
  197.   Reset(H);
  198. (*$I+*)
  199.   if IoResult = 0 then
  200.   begin
  201.     Handle := TextRec(H).Handle;                { Filehandle holen }
  202.     Old_Exit := ExitProc;           { Bei Ende/Abbruch muss 'H'... }
  203.     ExitProc := @CD_Exit;      { ...automatisch geschlossen werden }
  204.   end
  205.   else Handle := 0;
  206.   OpenCDHandle := Handle;
  207. end;
  208.  
  209. Procedure CloseCDHandle;
  210. begin
  211.   if TextRec(H).Mode <> FmClosed
  212.      then ExitProc := Old_Exit;     { Umleitung wieder zuruecknehmen }
  213.   Old_Exit := NIL;
  214. {$I-}
  215.   Close(H);
  216.   If IoResult = 0 then;             { 'H' schliessen, falls offen, }
  217. {$I+}                                     { evtl. Fehler verwerfen }
  218. end;
  219.  
  220.  
  221. function Red2HSG( Var Inf:TrkInfo ):LongInt;
  222. var l: longint;
  223. begin
  224.       l :=     LongInt(( Inf.Start shr 16 ) and $FF )  * 4500;
  225.       l := l + LongInt(( Inf.Start shr  8 ) and $FF )  * 75;
  226.       l := l + LongInt(( Inf.Start        ) and $FF ) ;
  227.  
  228.   Red2HSG := l -2;
  229. end;
  230.  
  231. function Red2Time( Var Inf:TrkInfo ):Word;
  232. begin
  233.   Red2Time:= (( Inf.Start shr 24 ) and $FF ) shl 8
  234.            + (( Inf.Start shr 16 ) and $FF )
  235. end;
  236.  
  237. function HSG2Red(L:Longint):Longint;
  238. begin
  239. end;
  240.  
  241. Function CD_IOCtl( Func, Len : Word) :  Boolean;
  242. begin
  243.   With R do
  244.   begin
  245.     AX := Func;
  246.     BX := OpenCDHandle;
  247.     CX := 129;
  248.     DS := DSeg;
  249.     ES := DS;
  250.     DX := Ofs(CtlBlk);
  251.     MsDos( R );
  252.     CD.Status := AX;
  253.     CD_IOCtl  := (Flags and FCARRY) = 0;
  254.     CloseCDHandle;
  255.   end
  256. end;
  257.  
  258.  
  259. Function CD_Reset: Boolean;
  260. begin
  261.   CtlBlk[0] := 2;   { reset }
  262.   CD_Reset  := CD_IoCtl( IoCtlWrite, 1)
  263. end;
  264.  
  265. Function DieTuer( AufZu:Byte ): Boolean;
  266. begin
  267.   CtlBlk[0] := 1;                                      { die Tuer.. }
  268.   CtlBlk[1] := AufZu;                                { ..freigeben }
  269.   DieTuer := CD_IoCTL(IoCtlWrite, 2);
  270. end;
  271.  
  272. Function CD_Open: Boolean;
  273. Const Auf = 0;
  274. begin
  275.  CD_Open := DieTuer( Auf );
  276. end;
  277.  
  278. Function CD_Close: Boolean;
  279. Const Zu = 1;
  280. begin
  281.  CD_Close := DieTuer( Zu );
  282. end;
  283.  
  284.  
  285. Function CD_Eject: Boolean;
  286. begin
  287.   CtlBlk[0] := 0;                                   { CD auswerfen }
  288.   CD_Eject  := CD_IOCtl(IoCtlWrite, 1);
  289. end;
  290.  
  291.  
  292. Function CD_Play(no:byte; len:integer):  Boolean;
  293. begin                                               { CD PlayAudio }
  294.  
  295.   FillChar(CtlBlk, sizeof(CtlBlk), 0);
  296.   CtlBlk[0] := 22;                             { laenge des req-hdr }
  297.   CtlBlk[1] := 0;                                       { sub-unit }
  298.   CtlBlk[2] := $84;                                     { Kommando }
  299.   CtlBlk[3] := 0;                                    { Status-WORT }
  300.   CtlBlk[4] := 0;
  301.   CtlBlk[5] := 0;
  302.   CtlBlk[13]:= CD.HSG_RB;                             { HSG-Modus }
  303.  
  304.   CD.Sector := VTOC.Titles[no].Start;          { ist im HSG-Format }
  305.  
  306.   Move( CD.Sector, CtlBlk[14], 4 );                 { Start-Sector }
  307.   if len = -1
  308.     then All := $FFFF
  309.     else All := len;
  310.   Move( All      , CtlBlk[18], 4 );               { Anzahl Sectoren}
  311.   ASM
  312.      mov  ax, $1510
  313.      push ds
  314.      pop  es
  315.      xor  cx, cx
  316.      mov  cl, CD.DrvNo
  317.      mov  bx, offset CtlBlk
  318.      Int $2f
  319.   end;
  320.  
  321.   CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
  322.   CD_Play   := CD.Status and $8000 = 0;
  323.  
  324. end;
  325.  
  326. function CD_VTOC:Boolean;
  327. Var i: byte;
  328.     l: longint;
  329. begin
  330.   FillChar( Tracks, Sizeof( Tracks ), 0);
  331.   CtlBlk[0] := 10;                               { Read LeadOut-Tr }
  332.   CD_IoCtl( IoCtlRead, 6);
  333.   move( CtlBlk[1], CD.LoAuTr, 6);
  334.   i := CD.HiAuTr+1;
  335.   move( CtlBlk[3], Tracks[i], 4);      { die Auslaufrille 8-) }
  336.   Tracks[i].Start := Red2Hsg(Tracks[i]);
  337.  
  338.   for i := CD.LoAuTr to CD.HiAuTr do
  339.   begin
  340.     FillChar(CtlBlk, sizeof(CtlBlk), 0);           { RED-Book-Format }
  341.     CtlBlk[0] := 11;                               { Read VTOC-Entry }
  342.     CtlBlk[1] := i;                                       { track-no }
  343.     CD_IoCtl( IoCtlRead, 6);
  344.     move( CtlBlk[1], Tracks[i], 6);
  345. {   Tracks[i].Start := Red2Hsg(Tracks[i]); }
  346.   end;
  347.  
  348.  
  349.   With VTOC do
  350.   begin
  351.     DiskName := '';
  352.     UAN_Code := '';
  353.     TrackCnt := CD.HiAuTr;
  354.     for i := CD.LoAuTr to CD.HiAuTr do
  355.     With Titles[i] do
  356.     begin
  357.       L := LongInt((Tracks[i+1].Start shr 16) and $FF) * 60
  358.         +         (Tracks[i+1].Start shr  8) and $FF
  359.         - ( LongInt((Tracks[i].Start shr 16) and $FF) * 60
  360.                  +  (Tracks[i].Start shr  8) and $FF);
  361.       Title  := '???';
  362.       RunMin := L div 60;
  363.       RunSec := l - RunMin*60;
  364.       Start  := Red2Hsg(Tracks[i]);
  365.     end
  366.   end;
  367.  
  368.  
  369.  
  370. end;
  371.  
  372. Function CD_Stop:  Boolean;
  373. begin                                               { CD StopAudio }
  374.   FillChar(CtlBlk, sizeof(CtlBlk), 0);
  375.   CtlBlk[0] := 5;                             { laenge des req-hdr }
  376.   CtlBlk[1] := 0;                                       { sub-unit }
  377.   CtlBlk[2] := $85;                                     { Kommando }
  378.   CtlBlk[3] := 0;                                    { Status-WORT }
  379.   CtlBlk[4] := 0;
  380.   CtlBlk[5] := 0;
  381.   ASM
  382.      mov  ax, $1510
  383.      push ds
  384.      pop  es
  385.      xor  cx, cx
  386.      mov  cl, CD.DrvNo
  387.      mov  bx, offset CtlBlk
  388.      Int $2f
  389.   end;
  390.  
  391.   CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
  392.   CD_Stop   := CD.Status and $8000 = 0;
  393.  
  394. end;
  395.  
  396.  
  397. Function CD_Resume:Boolean;
  398. begin                                                 { ResumeAudio}
  399.   CtlBlk[0] := 3;                              { laenge des req-hdr }
  400.   CtlBlk[1] := 0;                                       { sub-unit }
  401.   CtlBlk[2] := $88;                                     { Kommando }
  402.   CtlBlk[3] := 0;                                    { Status-WORT }
  403.   CtlBlk[4] := 0;
  404.   Asm
  405.      mov ax, Seg @DATA
  406.      mov es, ax
  407.      mov ax, DevDrvReq
  408.      lea bx, CtlBlk
  409.      Int 2fh
  410.   end;
  411.   CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
  412.   CD_Resume := CD.Status and $8000 = 0;
  413.  
  414. end;
  415.  
  416. Function CD_GetVol:Boolean;
  417. begin
  418.   CtlBlk[0] := 4;                           { die Lautstaerke lesen }
  419.   CD_GetVol := CD_IOCtl(IoCtlRead, 8);
  420.   if ((R.Flags and FCARRY) = 0)
  421.    then move(CtlBlk[1], CD.VolInfo, 8)
  422.    else FillChar( CD.VolInfo, 8, 0)
  423. end;
  424.  
  425. Function CD_SetVol:Boolean;
  426. begin
  427.   CtlBlk[0] := 3;                          { die Lautstaerke setzen }
  428.   CD_SetVol := CD_IOCtl( IoCtlWrite, 8);
  429. end;
  430.  
  431. Function CD_HeadAdr: Boolean;
  432. Var  L:longint;  S:String;
  433. begin
  434.   FillChar(CtlBlk, sizeof(CtlBlk), 0);
  435.   CtlBlk[0] := 1;
  436.   CtlBlk[1] := 1;                     { die Kopfposition im RED-Format }
  437.   CD_HeadAdr:= CD_IOCtl(IoCtlRead, 128);
  438.   if ((R.Flags and FCARRY) = 0)
  439.     then begin
  440.            move(CtlBlk[2], L, 4);
  441.            if CtlBlk[1] = 1 then
  442.            begin
  443.              STR( CtlBlk[4]:2, S);  CD_REDPos := S;
  444.              STR( CtlBlk[3]:2, S);  CD_REDPos := CD_REDPos+ ':'+ S;
  445.              CD.Sector := Longint(CtlBlk[4]) *4500 +
  446.                           Longint(CtlBlk[3]) *75   +
  447.                           Longint(CtlBlk[2])
  448.                           - 150;
  449.            end else
  450.            begin
  451.              CD.Sector := L;
  452.              STR(L:0,CD_HSGPos);
  453.            end
  454.  
  455.          end
  456.     else FillChar( CD.Sector, 4, 0);
  457. end;
  458.  
  459.  
  460. Function CD_Position:Boolean;
  461. var l : longint;
  462. begin
  463.   CtlBlk[0] := 12;                                  { Audio-Infos  }
  464.   CD_Position :=CD_IOCtl(IoCtlRead,10);
  465.   Move(CtlBlk[1], CD.CntAdr, 10);
  466. end;
  467.  
  468.  
  469. Procedure CD_GetUAN;
  470. begin
  471.   CtlBlk[0] := 14;                                  { EAN-Nummer   }
  472.   If CD_IOCtl(IoCtlRead,10)
  473.     then move(CtlBlk[1], CD.Uctrl, 10);
  474. end;
  475.  
  476.  
  477. Function CD_MediaChanged:Boolean;
  478. begin
  479.   CtlBlk[0] := 9;                                   { Media-Change }
  480.   If CD_IOCtl(IoCtlRead, 1)
  481.     then move(CtlBlk[1], CD.MedChg, 1 );
  482.   CD_MediaChanged:= CD.MedChg <> 1
  483. end;
  484.  
  485. Procedure CD_Info;
  486. begin
  487.  
  488.  { CD_Reset; }
  489.  
  490.   If CD_HeadAdr then;
  491.  
  492.   CtlBlk[0] := 6;                               { Device-parameter }
  493.   If CD_IOCtl(IoCtlRead, 4)
  494.     then move(CtlBlk[1], CD.DevPar, 4 );
  495.  
  496.   CtlBlk[0] := 7;                                   { Sector-Groesse }
  497.   If CD_IOCtl(IoCtlRead, 3)                              { & Modus }
  498.     then move(CtlBlk[1], CD.RawMode, 3 );
  499.  
  500.   CtlBlk[0] := 8;                                   { Volume-Groesse }
  501.   If CD_IOCtl(IoCtlRead, 4)
  502.     then move(CtlBlk[1], CD.VolSize, 4 );
  503.  
  504.   CtlBlk[0] := 12;                                  { Audio-Infos  }
  505.   If CD_IOCtl(IoCtlRead,10)
  506.     then move(CtlBlk[1], CD.CntAdr, 10);
  507.  
  508.   CtlBlk[0] := 11;                                  { Track-Infos  }
  509.   CtlBlk[1] := CtlBlk[2];                           { aktueller... }
  510.   If CD_IOCtl(IoCtlRead, 6)
  511.     then move(CtlBlk[1], CD.TrkNo, 6 );
  512.  
  513.   CD_VTOC;
  514.  
  515. end;
  516.  
  517. {========= minimale Initialisierung =============}
  518. begin
  519.   CD_Avail := CD_Init;
  520.   if CD_Avail then CD_INFO
  521. end.